Package Dependencies/ Data

N.B. There are codeblocks here which have been hidden by default as they are just repeats of the start of ‘code’. This just the point where in a new environment you would need to load up the same packages as before, and import/create the data in ‘code’, to make the below graphics produceable in R. Anything new starts after ///.

If you’d like to see this code, it’s visible in the .rmd at ‘Map_Code.Rmd’.. Or directly from github https://github.com/fergustaylor/Arran (in /docs).

///

Mapping

Load the packages

library(rgdal)
library(leaflet)
library(ggmap)

Coordinates

postcodelist <- paste(unique(arrancoordinates$listID), "Postcodes", sep=" ")
datazonelist <- paste(unique(arrancoordinates$listID), "Datazones", sep=" ")
m = leaflet() %>% addTiles() %>% setView(-5.227680, 55.582338, zoom = 10) 

Create some labels for the maps.

Map1

m %>% 
#allcoordinates
addMarkers(
    lng = arrancoordinates$longitude, lat = arrancoordinates$latitude,
    label = arrancoordinates$postcode,
    labelOptions = labelOptions(noHide = F), group = "Postcode Plots") %>%
hideGroup("All Postcode Plots") %>% 
#alldatazones  
addPolygons(data=exampleshapes, 
            weight = 2, 
            label = datazonelist,
            group = "All Datazones") %>% 
hideGroup("Datazones") %>% 
  
#selectcoordinates
addMarkers(
    lng = arrancoordinates$longitude, lat = arrancoordinates$latitude,
    label = arrancoordinates$postcode,
    labelOptions = labelOptions(noHide = F), group = arrancoordinates$listID) %>% 
hideGroup(arrancoordinates$listID) %>% 
#selectdatazone
addPolygons(data = exampleshapes[1] , 
            weight = 2, label = datazonelist[1], group = datazonelist[1]) %>% 
addPolygons(data = exampleshapes[2] , 
            weight = 2, label = datazonelist[2], group = datazonelist[2]) %>% 
addPolygons(data = exampleshapes[3] , 
            weight = 2, label = datazonelist[3], group = datazonelist[3]) %>% 
addPolygons(data = exampleshapes[4] , 
            weight = 2, label = datazonelist[4], group = datazonelist[4]) %>% 
addPolygons(data = exampleshapes[5] , 
            weight = 2, label = datazonelist[5], group = datazonelist[5]) %>% 
addPolygons(data = exampleshapes[6] , 
            weight = 2, label = datazonelist[6], group = datazonelist[6]) %>% 
addPolygons(data = exampleshapes[7] , 
            weight = 2, label = datazonelist[7], group = datazonelist[7]) %>% 
hideGroup(datazonelist[1]) %>%
hideGroup(datazonelist[2]) %>%
hideGroup(datazonelist[3]) %>%
hideGroup(datazonelist[4]) %>%
hideGroup(datazonelist[5]) %>%
hideGroup(datazonelist[6]) %>%
hideGroup(datazonelist[7]) %>%
#Layers control
addLayersControl(
    baseGroups = c("All Datazones", "Postcode Plots", "Nothing"),
    overlayGroups = c(arrancoordinates$listID, datazonelist),
    options = layersControlOptions(collapsed = TRUE)
  )

Example Markers

Inputing example markers.

cliniccoordinates <- read.csv("../alldata/clinics.csv") %>%
dplyr::left_join(arrancoordinates, by="postcode")
Column `postcode` joining factors with different levels, coercing to character vector
#change to character
cliniccoordinates$X <- as.character(cliniccoordinates$X)

Map2

m %>%
#allcoordinates
addMarkers(
    lng = arrancoordinates$longitude, lat = arrancoordinates$latitude,
    label = arrancoordinates$postcode,
    labelOptions = labelOptions(noHide = F), group = "All Postcode Plots") %>%
hideGroup("All Postcode Plots") %>% 
#alldatazones  
addPolygons(data=exampleshapes, 
            weight = 2, 
            label = datazonelist,
            group = "All Datazones",
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("All Datazones") %>% 
#cliniccoordinates
addMarkers(
    lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
    label = cliniccoordinates$X,
    labelOptions = labelOptions(noHide = F), group = "All GP clinics") %>%
  hideGroup("All GP clinics") %>%   
#cliniccoordinates
addMarkers(
    lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
    label = cliniccoordinates$X,
    labelOptions = labelOptions(noHide = F), group = cliniccoordinates$X) %>%
  hideGroup(cliniccoordinates$X) %>%   
  
#Layers control
addLayersControl(
    baseGroups = c("All Datazones", "All Postcode Plots", "All GP clinics", "Nothing"),
    overlayGroups = c(cliniccoordinates$X),
    options = layersControlOptions(collapsed = TRUE)
  )

Map3

Overlaying percentiles

exampleshapes2 <- as(arransimd, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))

Creating a palate for percentiles

pal2 <- colorNumeric(
  palette = "viridis",
  domain = exampleshapes2$Percentile)

Creating the percentile labels

listlistlist <- paste(datazonelist, exampleshapes2$Percentile, sep=" ") %>%
paste("%", sep="")

Map

m %>% 
#alldatazones  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2004, ], 
            weight = 2, 
            label = listlistlist[29:35],
            group = "2004",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2004") %>% 
  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2006, ], 
            weight = 2, 
            label = listlistlist[22:28],
            group = "2006",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2006") %>% 
  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2009, ], 
            weight = 2, 
            label = listlistlist[15:21],
            group = "2009",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2009") %>% 
  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2012, ], 
            weight = 2, 
            label = listlistlist[8:14],
            group = "2012",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2012") %>% 
addPolygons(data=exampleshapes2[exampleshapes2$year == 2016, ], 
            weight = 2, 
            label = listlistlist[1:7],
            group = "2016",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2016") %>% 
  
#cliniccoordinates
addMarkers(
    lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
    label = cliniccoordinates$X,
    labelOptions = labelOptions(noHide = F), group = cliniccoordinates$X) %>%
  hideGroup(cliniccoordinates$X) %>%   
addLegend("bottomleft", pal = pal2, values = exampleshapes2$Percentile,
    title = "SIMD Percentile",
    labFormat = labelFormat(suffix = "%"),
    opacity = 1
  )  %>%  
#Layers control
addLayersControl(
    baseGroups = c("2004", "2006", "2009", "2012", "2016", "Nothing"),
    overlayGroups = c(cliniccoordinates$X),
    options = layersControlOptions(collapsed = TRUE)
  )

Map4 Arran vs. Scotland

Beautiful map, but I have to leave the laptop running overnight to compile it.

#Import UK data
DZBoundaries2016 <- read_sf("../alldata/SG_SIMD_2016")
Scotland2016 <- as(DZBoundaries2016, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))

DZBoundaries2012 <- read_sf("../alldata/SG_SIMD_2012")
Scotland2012 <- as(DZBoundaries2012, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))

DZBoundaries2009 <- read_sf("../alldata/SG_SIMD_2009")
Scotland2009 <- as(DZBoundaries2009, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))

DZBoundaries2006 <- read_sf("../alldata/SG_SIMD_2006")
Scotland2006 <- as(DZBoundaries2006, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))

DZBoundaries2004 <- read_sf("../alldata/SG_SIMD_2004")
Scotland2004 <- as(DZBoundaries2004, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))

#Colour Palate
pal2 <- colorNumeric(
  palette = "viridis",
  domain = 0:100)

leaflet() %>% 
  addTiles() %>% 
  setView(-5.227680, 55.582338, zoom = 10) %>% 

addPolygons(data=exampleshapes2[exampleshapes2$year == 2004, ], 
            weight = 2, 
            label = listlistlist[29:35],
            group = "2004",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2004") %>% 
  
addPolygons(data=Scotland2004, 
            weight = 2, 
            group = "Scotland 2004",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("Scotland 2004") %>% 
  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2006, ], 
            weight = 2, 
            label = listlistlist[22:28],
            group = "2006",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2006") %>% 

addPolygons(data=Scotland2006, 
            weight = 2, 
            group = "Scotland 2006",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("Scotland 2006") %>% 
  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2009, ], 
            weight = 2, 
            label = listlistlist[15:21],
            group = "2009",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2009") %>% 

addPolygons(data=Scotland2009, 
            weight = 2, 
            group = "Scotland 2009",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("Scotland 2009") %>% 
  
addPolygons(data=exampleshapes2[exampleshapes2$year == 2012, ], 
            weight = 2, 
            label = listlistlist[8:14],
            group = "2012",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2012") %>% 
  
addPolygons(data=Scotland2012, 
            weight = 2, 
            group = "Scotland 2012",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("Scotland 2012") %>% 

addPolygons(data=exampleshapes2[exampleshapes2$year == 2016, ], 
            weight = 2, 
            label = listlistlist[1:7],
            group = "2016",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("2016") %>% 

addPolygons(data=Scotland2016, 
            weight = 2, 
            group = "Scotland 2016",
            fillOpacity =0.8,
            color = ~pal2(Percentile),
            highlightOptions = highlightOptions(color = "black", weight = 2,
      bringToFront = TRUE)) %>% 
hideGroup("Scotland 2016") %>% 
  
addMarkers(
    lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
    label = cliniccoordinates$X,
    labelOptions = labelOptions(noHide = F), group = cliniccoordinates$X) %>%
  hideGroup(cliniccoordinates$X) %>%   

addLegend("bottomleft", pal = pal2, values = exampleshapes2$Percentile,
    title = "SIMD Percentile",
    labFormat = labelFormat(suffix = "%"),
    opacity = 1
  )  %>%  

addLayersControl(
    baseGroups = c("2004", "Scotland 2004", "2006", "Scotland 2006", "2009", "Scotland 2009", "2012", "Scotland 2012", "2016", "Scotland 2016", "Nothing"),
    overlayGroups = c(cliniccoordinates$X),
    options = layersControlOptions(collapsed = TRUE)
  )

Map4 Arran vs. Scotland Map

Map4

Map4

Map5

I’ll continue this on a new document so I can knit it to an html website.

Map5.

Map5 Code.

But the development is that I’ve used intersect() on each filtered ‘SG_SIMD_…’ to create the ‘sharedvariables’ vector, so I was able to create a new dataframe of every year with only shared variables, rather than percentile alone which I originally used as an example to practice the maps on (my previous version of ‘arransimd’). The new ‘arranSIMD’ can then have a version of map3 for each shared variable.

Go back.

LS0tCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKI1BhY2thZ2UgRGVwZW5kZW5jaWVzLyBEYXRhCk4uQi4gVGhlcmUgYXJlIGNvZGVibG9ja3MgaGVyZSB3aGljaCBoYXZlIGJlZW4gaGlkZGVuIGJ5IGRlZmF1bHQgYXMgdGhleSBhcmUganVzdCByZXBlYXRzIG9mIHRoZSBzdGFydCBvZiBbJ2NvZGUnLl0oQ29kZS5odG1sKSAKVGhpcyBqdXN0IHRoZSBwb2ludCB3aGVyZSBpbiBhIG5ldyBlbnZpcm9ubWVudCB5b3Ugd291bGQgbmVlZCB0byBsb2FkIHVwIHRoZSBzYW1lIHBhY2thZ2VzIGFzIGJlZm9yZSwgYW5kIGltcG9ydC9jcmVhdGUgdGhlIGRhdGEgaW4gJ2NvZGUnLCB0byBtYWtlIHRoZSBiZWxvdyBncmFwaGljcyBwcm9kdWNlYWJsZSBpbiBSLgpBbnl0aGluZyBuZXcgc3RhcnRzIGFmdGVyIC8vLy4KCklmIHlvdSdkIGxpa2UgdG8gc2VlIHRoaXMgY29kZSwgaXQncyB2aXNpYmxlIGluIHRoZSAucm1kIGF0IFsnTWFwX0NvZGUuUm1kJy5dKE1hcF9Db2RlLlJtZCkuIE9yIGRpcmVjdGx5IGZyb20gZ2l0aHViIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJndXN0YXlsb3IvQXJyYW4gKGluIC9kb2NzKS4KCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMjTG9hZCBQYWNrYWdlcwojRmlyc3QgSSBuZWVkIHRvIGxvYWQgdXAgdGhlIHBhY2thZ2VzIEknbGwgbmVlZApsaWJyYXJ5KHNmKQpsaWJyYXJ5KGdncGxvdDIpICNkZXZlbG9wbWVudCB2ZXJzaW9uIQojIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInRpZHl2ZXJzZS9nZ3Bsb3QyIikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShzcCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShwbHlyKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMjSW1wb3J0IFBvc3Rjb2RlIERhdGEKI05vdyBJIGltcG9ydCBteSBkYXRhLiBJIGZpbHRlciBmb3IgdGhlIEFycmFuIHBvc3Rjb2RlcywgKHNpbmNlIEFycmFuIGFsbCBiZWdpbnMgJ0tBMjcnKS4KI0FkZCBkb3dubG9hZCBjb21tYW5kcyBmb3IgZGF0YS4KIyMgRmluZGluZyB0aGUgQXJyYW4gY29vcmRpbmF0ZXMKYXJyYW5jb29yZGluYXRlcyA8LSByZWFkLmNzdigiLi4vYWxsZGF0YS91a3Bvc3Rjb2Rlcy5jc3YiKSAlPiUKIGZpbHRlcihzdWJzdHIocG9zdGNvZGUsMSw0KT09IktBMjciKQoKI0ZpbmQgd2F5IHRvIHJlcGxhY2Ugd2l0aCBleGlzdGluZyBTSU1EIHNoYXBlIGZpbGVzCmFycmFuc3Vic2VjdCA8LSByZWFkX3NmKCIuLi9hbGxkYXRhL1Njb3RsYW5kX3Bjc18yMDExIikgJT4lCmZpbHRlcihzdWJzdHIobGFiZWwsMSw0KT09IktBMjciKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMjSW1wb3J0IFNJTUQgZGF0YQojTm93IEkgbG9hZCB0aGUgU0lNRCBkYXRhLCBjb250YWluaW5nIHRoZSBnZW9tZXRyaWVzIChzaGFwZWZpbGVzKSBhbmQgU0lNRCBkYXRhIChwZXJjZW50aWxlcywgZXRjKQpyZW9yZGVyZWR2ZWN0b3I8LSBjKCJTMDEwMTExNzQiLCAiUzAxMDExMTcxIiwgIlMwMTAxMTE3NyIsICJTMDEwMTExNzYiLCAiUzAxMDExMTc1IiwgIlMwMTAxMTE3MyIsICJTMDEwMTExNzIiICkKCmFycmFuMjAxNiA8LSByZWFkX3NmKCIuLi9hbGxkYXRhL1NHX1NJTURfMjAxNiIpW2MoNDY3Miw0NjY2LDQ2NjksNDY3MSw0NjY3LDQ2NjgsNDY3MCksXSAlPiUKICBzbGljZShtYXRjaChyZW9yZGVyZWR2ZWN0b3IsIERhdGFab25lKSkKCkFycmFuZHoyMDEyIDwtIGMoNDQwOSw0MzcyLDQzNTMsNDM1Miw0MzUxLDQzNTAsNDM0OSkKCmFycmFuMjAxMiA8LSByZWFkX3NmKCIuLi9hbGxkYXRhL1NHX1NJTURfMjAxMiIpW0FycmFuZHoyMDEyLF0KYXJyYW4yMDA5IDwtIHJlYWRfc2YoIi4uL2FsbGRhdGEvU0dfU0lNRF8yMDA5IilbQXJyYW5kejIwMTIsXQphcnJhbjIwMDYgPC0gcmVhZF9zZigiLi4vYWxsZGF0YS9TR19TSU1EXzIwMDYiKVtBcnJhbmR6MjAxMixdCmFycmFuMjAwNCA8LSByZWFkX3NmKCIuLi9hbGxkYXRhL1NHX1NJTURfMjAwNCIpW0FycmFuZHoyMDEyLF0KCnNoYXJlZHZhcmlhYmxlcyA8LSBpbnRlcnNlY3QoY29sbmFtZXMoYXJyYW4yMDE2KSwgY29sbmFtZXMoYXJyYW4yMDEyKSkgJT4lCiAgaW50ZXJzZWN0KGNvbG5hbWVzKGFycmFuMjAwOSkpICAlPiUKICBpbnRlcnNlY3QoY29sbmFtZXMoYXJyYW4yMDA2KSkgICU+JQogIGludGVyc2VjdChjb2xuYW1lcyhhcnJhbjIwMDQpKQogIAphcnJhbjIwMTYyIDwtIGFycmFuMjAxNiAlPiUKICBzZWxlY3Qoc2hhcmVkdmFyaWFibGVzKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAxNiIpCmFycmFuMjAxMjIgPC0gYXJyYW4yMDEyICU+JQogIHNlbGVjdChzaGFyZWR2YXJpYWJsZXMpICU+JQogIG11dGF0ZSh5ZWFyPSIyMDEyIikKYXJyYW4yMDA5MiA8LSBhcnJhbjIwMDkgJT4lCiAgc2VsZWN0KHNoYXJlZHZhcmlhYmxlcykgJT4lCiAgbXV0YXRlKHllYXI9IjIwMDkiKQphcnJhbjIwMDYyIDwtIGFycmFuMjAwNiAlPiUKICBzZWxlY3Qoc2hhcmVkdmFyaWFibGVzKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwNiIpCmFycmFuMjAwNDIgPC0gYXJyYW4yMDA0ICU+JQogIHNlbGVjdChzaGFyZWR2YXJpYWJsZXMpICU+JQogIG11dGF0ZSh5ZWFyPSIyMDA0IikKCmFycmFuc2ltZCA8LSByYmluZChhcnJhbjIwMTYyLGFycmFuMjAxMjIsYXJyYW4yMDA5MixhcnJhbjIwMDYyLGFycmFuMjAwNDIpICU+JQptdXRhdGUoCiAgICBsb24gPSBtYXBfZGJsKGdlb21ldHJ5LCB+c3RfY2VudHJvaWQoLngpW1sxXV0pLAogICAgbGF0ID0gbWFwX2RibChnZW9tZXRyeSwgfnN0X2NlbnRyb2lkKC54KVtbMl1dKQogICAgKQoKYXJyYW5zaW1kJGxpc3RJRCA8LSByZXZhbHVlKGFycmFuc2ltZCREYXRhWm9uZSwKICAgICAgICAgICAgICAgYygiUzAxMDA0NDA5Ij0iUzAxMDA0NDA5L1MwMTAxMTE3NCIsICJTMDEwMDQzNzIiPSJTMDEwMDQzNzIvUzAxMDExMTcxIiwgIlMwMTAwNDM1MyI9IlMwMTAwNDM1My9TMDEwMTExNzciLCAiUzAxMDA0MzUyIj0iUzAxMDA0MzUyL1MwMTAxMTE3NiIsICJTMDEwMDQzNTEiPSJTMDEwMDQzNTEvUzAxMDExMTc1IiwgIlMwMTAwNDM1MCI9IlMwMTAwNDM1MC9TMDEwMTExNzMiLCAiUzAxMDA0MzQ5Ij0iUzAxMDA0MzQ5L1MwMTAxMTE3MiIsICJTMDEwMTExNzQiPSJTMDEwMDQ0MDkvUzAxMDExMTc0IiwgIlMwMTAxMTE3MSI9IlMwMTAwNDM3Mi9TMDEwMTExNzEiLCAiUzAxMDExMTc3Ij0iUzAxMDA0MzUzL1MwMTAxMTE3NyIsICJTMDEwMTExNzYiPSJTMDEwMDQzNTIvUzAxMDExMTc2IiwgIlMwMTAxMTE3NSI9IlMwMTAwNDM1MS9TMDEwMTExNzUiLCAiUzAxMDExMTczIj0iUzAxMDA0MzUwL1MwMTAxMTE3MyIsICJTMDEwMTExNzIiPSJTMDEwMDQzNDkvUzAxMDExMTcyIikpCmBgYAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KI05vdyBJIHdhbnQgdG8gb3ZlcmxheSB0aGUgcG9zdGNvZGVzIGJ5IERhdGF6b25lLgojVG8gZG8gdGhpcyBJJ3ZlIGNvbnZlcnRlZCBib3RoIHRoZSBBcnJhbiBjb29yZGluYXRlcyBhbmQgQXJyYW4gKDIwMTYpIHNoYXBlZmlsZXMgaW50byBzcGF0aWFsIHBvaW50cy9wb2x5Z29ucywgY29udmVydGVkIHRoZW0gaW50byBhIGNvbW1vbiBDUlMsIGFuZCB0aGVuIGNvbXBhcmVkIHRoZW0gYnkgdXNpbmcgJ3BseXI6Om92ZXIoKScuCiNUaGlzIGdpdmVzIG1lIHRoZSBvYmplY3QgJ25hbWluZ2R6cG9zdGNvZGUnLCB3aXRoIHRoZSBwb3N0Y29kZSByb3dzIGdyb3VwZWQgaW50byBJRHMgKHVuaWRlbnRpZmllZCBkYXRhem9uZXMpLgpzaW1wbGUuc2YgPC0gc3RfYXNfc2YoYXJyYW5jb29yZGluYXRlcywgY29vcmRzPWMoJ2xvbmdpdHVkZScsJ2xhdGl0dWRlJykpCnN0X2NycyhzaW1wbGUuc2YpIDwtIDQzMjYKCmV4YW1wbGVzaGFwZXMgPC0gc2Y6Ojphc19TcGF0aWFsKGFycmFuMjAxNiRnZW9tZXRyeSkgJT4lCiAgc3BUcmFuc2Zvcm0oQ1JTKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCIpKQoKZXhhbXBsZXBvaW50cyA8LSBzZjo6OmFzX1NwYXRpYWwoc2ltcGxlLnNmJGdlb20pICU+JQogIHNwVHJhbnNmb3JtKENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKCm5hbWluZ2R6cG9zdGNvZGUgPC0gb3ZlcihleGFtcGxlc2hhcGVzLCBleGFtcGxlcG9pbnRzLCByZXR1cm5MaXN0ID0gVFJVRSkKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojSSBjYW4gdGhlbiB0YWtlIGEgbWVtYmVyIHJlZmVyZW5jZSBmcm9tIHRoZSBvcmdpbmFsIHBvc3Rjb2RlIGxpc3QsIHdoaWNoIGdpdmVzIG1lIGEgc2VsZWN0aW9uIG9mIHRoZSByb3dzIGluIHRoYXQgRFouIEZvciBzaW1wbGljaXR5IEkndmUgd3JpdHRlbiB0aGlzIGFzIGEgbmV3IGZ1bmN0aW9uLiAKIyNNdXRhdGUgYXJyYW5jb29yZGluYXRlcyB0byBsYWJlbCB0aGUgSURzCmZ1bmN0aW9uMTAwIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGFyZ3VtZW50IDwtIGFycmFuY29vcmRpbmF0ZXNbbmFtaW5nZHpwb3N0Y29kZVtbYXJndW1lbnRdXSxdICU+JSBtdXRhdGUoRGF0YVpvbmU9YXJndW1lbnQpCn0KCmFycmFuY29vcmRpbmF0ZXMgPC0gbGFwcGx5KDE6NyxmdW5jdGlvbjEwMCkKYXJyYW5jb29yZGluYXRlcyA8LSByYmluZChhcnJhbmNvb3JkaW5hdGVzW1sxXV0sIGFycmFuY29vcmRpbmF0ZXNbWzJdXSwgYXJyYW5jb29yZGluYXRlc1tbM11dLCBhcnJhbmNvb3JkaW5hdGVzW1s0XV0sIGFycmFuY29vcmRpbmF0ZXNbWzVdXSwgYXJyYW5jb29yZGluYXRlc1tbNl1dLCBhcnJhbmNvb3JkaW5hdGVzW1s3XV0pCgphcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCA8LSByZXZhbHVlKGFzLmNoYXJhY3RlcihhcnJhbmNvb3JkaW5hdGVzJERhdGFab25lKSwKICAgICAgICAgICAgICAgYygnMSc9IlMwMTAwNDQwOS9TMDEwMTExNzQiLCAnMic9IlMwMTAwNDM3Mi9TMDEwMTExNzEiLCAnMyc9IlMwMTAwNDM1My9TMDEwMTExNzciLCAnNCc9IlMwMTAwNDM1Mi9TMDEwMTExNzYiLCAnNSc9IlMwMTAwNDM1MS9TMDEwMTExNzUiLCAnNic9IlMwMTAwNDM1MC9TMDEwMTExNzMiLCAnNyc9IlMwMTAwNDM0OS9TMDEwMTExNzIiKSkKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojI0xhYmVsbGluZyB0aGUgbmFtaW5nZHpwb3N0Y29kZSBsaXN0Cm5hbWVzKG5hbWluZ2R6cG9zdGNvZGUpIDwtIGModW5pcXVlKGFycmFuc2ltZCRsaXN0SUQpKQpgYGAKCi8vLwoKI01hcHBpbmcKCiMjTG9hZCB0aGUgcGFja2FnZXMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShyZ2RhbCkKbGlicmFyeShsZWFmbGV0KQpsaWJyYXJ5KGdnbWFwKQpgYGAKCiMjQ29vcmRpbmF0ZXMKYGBge3J9CnBvc3Rjb2RlbGlzdCA8LSBwYXN0ZSh1bmlxdWUoYXJyYW5jb29yZGluYXRlcyRsaXN0SUQpLCAiUG9zdGNvZGVzIiwgc2VwPSIgIikKZGF0YXpvbmVsaXN0IDwtIHBhc3RlKHVuaXF1ZShhcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCksICJEYXRhem9uZXMiLCBzZXA9IiAiKQoKbSA9IGxlYWZsZXQoKSAlPiUgYWRkVGlsZXMoKSAlPiUgc2V0VmlldygtNS4yMjc2ODAsIDU1LjU4MjMzOCwgem9vbSA9IDEwKSAKYGBgCgpDcmVhdGUgc29tZSBsYWJlbHMgZm9yIHRoZSBtYXBzLgoKI01hcDEKYGBge3J9Cm0gJT4lIAoKI2FsbGNvb3JkaW5hdGVzCmFkZE1hcmtlcnMoCiAgICBsbmcgPSBhcnJhbmNvb3JkaW5hdGVzJGxvbmdpdHVkZSwgbGF0ID0gYXJyYW5jb29yZGluYXRlcyRsYXRpdHVkZSwKICAgIGxhYmVsID0gYXJyYW5jb29yZGluYXRlcyRwb3N0Y29kZSwKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBGKSwgZ3JvdXAgPSAiUG9zdGNvZGUgUGxvdHMiKSAlPiUKaGlkZUdyb3VwKCJBbGwgUG9zdGNvZGUgUGxvdHMiKSAlPiUgCgojYWxsZGF0YXpvbmVzICAKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gZGF0YXpvbmVsaXN0LAogICAgICAgICAgICBncm91cCA9ICJBbGwgRGF0YXpvbmVzIikgJT4lIApoaWRlR3JvdXAoIkRhdGF6b25lcyIpICU+JSAKICAKI3NlbGVjdGNvb3JkaW5hdGVzCmFkZE1hcmtlcnMoCiAgICBsbmcgPSBhcnJhbmNvb3JkaW5hdGVzJGxvbmdpdHVkZSwgbGF0ID0gYXJyYW5jb29yZGluYXRlcyRsYXRpdHVkZSwKICAgIGxhYmVsID0gYXJyYW5jb29yZGluYXRlcyRwb3N0Y29kZSwKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBGKSwgZ3JvdXAgPSBhcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCkgJT4lIApoaWRlR3JvdXAoYXJyYW5jb29yZGluYXRlcyRsaXN0SUQpICU+JSAKCiNzZWxlY3RkYXRhem9uZQphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1sxXSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFsxXSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbMV0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbMl0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbMl0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzJdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzNdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzNdLCBncm91cCA9IGRhdGF6b25lbGlzdFszXSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1s0XSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFs0XSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbNF0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbNV0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbNV0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzVdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzZdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzZdLCBncm91cCA9IGRhdGF6b25lbGlzdFs2XSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1s3XSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFs3XSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbN10pICU+JSAKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFsxXSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbMl0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzNdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFs0XSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbNV0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzZdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFs3XSkgJT4lCgojTGF5ZXJzIGNvbnRyb2wKYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCJBbGwgRGF0YXpvbmVzIiwgIlBvc3Rjb2RlIFBsb3RzIiwgIk5vdGhpbmciKSwKICAgIG92ZXJsYXlHcm91cHMgPSBjKGFycmFuY29vcmRpbmF0ZXMkbGlzdElELCBkYXRhem9uZWxpc3QpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpCiAgKQpgYGAKCiNFeGFtcGxlIE1hcmtlcnMKSW5wdXRpbmcgZXhhbXBsZSBtYXJrZXJzLgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjbGluaWNjb29yZGluYXRlcyA8LSByZWFkLmNzdigiLi4vYWxsZGF0YS9jbGluaWNzLmNzdiIpICU+JQpkcGx5cjo6bGVmdF9qb2luKGFycmFuY29vcmRpbmF0ZXMsIGJ5PSJwb3N0Y29kZSIpCiNjaGFuZ2UgdG8gY2hhcmFjdGVyCmNsaW5pY2Nvb3JkaW5hdGVzJFggPC0gYXMuY2hhcmFjdGVyKGNsaW5pY2Nvb3JkaW5hdGVzJFgpCmBgYAoKI01hcDIKYGBge3J9Cm0gJT4lCgojYWxsY29vcmRpbmF0ZXMKYWRkTWFya2VycygKICAgIGxuZyA9IGFycmFuY29vcmRpbmF0ZXMkbG9uZ2l0dWRlLCBsYXQgPSBhcnJhbmNvb3JkaW5hdGVzJGxhdGl0dWRlLAogICAgbGFiZWwgPSBhcnJhbmNvb3JkaW5hdGVzJHBvc3Rjb2RlLAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IEYpLCBncm91cCA9ICJBbGwgUG9zdGNvZGUgUGxvdHMiKSAlPiUKaGlkZUdyb3VwKCJBbGwgUG9zdGNvZGUgUGxvdHMiKSAlPiUgCgojYWxsZGF0YXpvbmVzICAKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gZGF0YXpvbmVsaXN0LAogICAgICAgICAgICBncm91cCA9ICJBbGwgRGF0YXpvbmVzIiwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIkFsbCBEYXRhem9uZXMiKSAlPiUgCgojY2xpbmljY29vcmRpbmF0ZXMKYWRkTWFya2VycygKICAgIGxuZyA9IGNsaW5pY2Nvb3JkaW5hdGVzJGxvbmdpdHVkZSwgbGF0ID0gY2xpbmljY29vcmRpbmF0ZXMkbGF0aXR1ZGUsCiAgICBsYWJlbCA9IGNsaW5pY2Nvb3JkaW5hdGVzJFgsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMobm9IaWRlID0gRiksIGdyb3VwID0gIkFsbCBHUCBjbGluaWNzIikgJT4lCiAgaGlkZUdyb3VwKCJBbGwgR1AgY2xpbmljcyIpICU+JSAgIAoKI2NsaW5pY2Nvb3JkaW5hdGVzCmFkZE1hcmtlcnMoCiAgICBsbmcgPSBjbGluaWNjb29yZGluYXRlcyRsb25naXR1ZGUsIGxhdCA9IGNsaW5pY2Nvb3JkaW5hdGVzJGxhdGl0dWRlLAogICAgbGFiZWwgPSBjbGluaWNjb29yZGluYXRlcyRYLAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IEYpLCBncm91cCA9IGNsaW5pY2Nvb3JkaW5hdGVzJFgpICU+JQogIGhpZGVHcm91cChjbGluaWNjb29yZGluYXRlcyRYKSAlPiUgICAKICAKI0xheWVycyBjb250cm9sCmFkZExheWVyc0NvbnRyb2woCiAgICBiYXNlR3JvdXBzID0gYygiQWxsIERhdGF6b25lcyIsICJBbGwgUG9zdGNvZGUgUGxvdHMiLCAiQWxsIEdQIGNsaW5pY3MiLCAiTm90aGluZyIpLAogICAgb3ZlcmxheUdyb3VwcyA9IGMoY2xpbmljY29vcmRpbmF0ZXMkWCksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApCmBgYAoKI01hcDMKIyNPdmVybGF5aW5nIHBlcmNlbnRpbGVzCmBgYHtyfQpleGFtcGxlc2hhcGVzMiA8LSBhcyhhcnJhbnNpbWQsICJTcGF0aWFsIikgJT4lCnNwVHJhbnNmb3JtKENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKYGBgCgojI0NyZWF0aW5nIGEgcGFsYXRlIGZvciBwZXJjZW50aWxlcwpgYGB7cn0KcGFsMiA8LSBjb2xvck51bWVyaWMoCiAgcGFsZXR0ZSA9ICJ2aXJpZGlzIiwKICBkb21haW4gPSBleGFtcGxlc2hhcGVzMiRQZXJjZW50aWxlKQpgYGAKCiMjQ3JlYXRpbmcgdGhlIHBlcmNlbnRpbGUgbGFiZWxzCmBgYHtyfQpsaXN0bGlzdGxpc3QgPC0gcGFzdGUoZGF0YXpvbmVsaXN0LCBleGFtcGxlc2hhcGVzMiRQZXJjZW50aWxlLCBzZXA9IiAiKSAlPiUKcGFzdGUoIiUiLCBzZXA9IiIpCmBgYAoKIyNNYXAKYGBge3J9Cm0gJT4lIAoKI2FsbGRhdGF6b25lcyAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlczJbZXhhbXBsZXNoYXBlczIkeWVhciA9PSAyMDA0LCBdLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gbGlzdGxpc3RsaXN0WzI5OjM1XSwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAwNCIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDA0IikgJT4lIAogIAphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMyW2V4YW1wbGVzaGFwZXMyJHllYXIgPT0gMjAwNiwgXSwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGxpc3RsaXN0bGlzdFsyMjoyOF0sCiAgICAgICAgICAgIGdyb3VwID0gIjIwMDYiLAogICAgICAgICAgICBmaWxsT3BhY2l0eSA9MC44LAogICAgICAgICAgICBjb2xvciA9IH5wYWwyKFBlcmNlbnRpbGUpLAogICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJibGFjayIsIHdlaWdodCA9IDIsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpKSAlPiUgCmhpZGVHcm91cCgiMjAwNiIpICU+JSAKICAKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzMltleGFtcGxlc2hhcGVzMiR5ZWFyID09IDIwMDksIF0sIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgbGFiZWwgPSBsaXN0bGlzdGxpc3RbMTU6MjFdLAogICAgICAgICAgICBncm91cCA9ICIyMDA5IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMDkiKSAlPiUgCiAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlczJbZXhhbXBsZXNoYXBlczIkeWVhciA9PSAyMDEyLCBdLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gbGlzdGxpc3RsaXN0Wzg6MTRdLAogICAgICAgICAgICBncm91cCA9ICIyMDEyIiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMTIiKSAlPiUgCgphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMyW2V4YW1wbGVzaGFwZXMyJHllYXIgPT0gMjAxNiwgXSwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGxpc3RsaXN0bGlzdFsxOjddLAogICAgICAgICAgICBncm91cCA9ICIyMDE2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMTYiKSAlPiUgCiAgCiNjbGluaWNjb29yZGluYXRlcwphZGRNYXJrZXJzKAogICAgbG5nID0gY2xpbmljY29vcmRpbmF0ZXMkbG9uZ2l0dWRlLCBsYXQgPSBjbGluaWNjb29yZGluYXRlcyRsYXRpdHVkZSwKICAgIGxhYmVsID0gY2xpbmljY29vcmRpbmF0ZXMkWCwKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBGKSwgZ3JvdXAgPSBjbGluaWNjb29yZGluYXRlcyRYKSAlPiUKICBoaWRlR3JvdXAoY2xpbmljY29vcmRpbmF0ZXMkWCkgJT4lICAgCgphZGRMZWdlbmQoImJvdHRvbWxlZnQiLCBwYWwgPSBwYWwyLCB2YWx1ZXMgPSBleGFtcGxlc2hhcGVzMiRQZXJjZW50aWxlLAogICAgdGl0bGUgPSAiU0lNRCBQZXJjZW50aWxlIiwKICAgIGxhYkZvcm1hdCA9IGxhYmVsRm9ybWF0KHN1ZmZpeCA9ICIlIiksCiAgICBvcGFjaXR5ID0gMQogICkgICU+JSAgCgojTGF5ZXJzIGNvbnRyb2wKYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCIyMDA0IiwgIjIwMDYiLCAiMjAwOSIsICIyMDEyIiwgIjIwMTYiLCAiTm90aGluZyIpLAogICAgb3ZlcmxheUdyb3VwcyA9IGMoY2xpbmljY29vcmRpbmF0ZXMkWCksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApCmBgYAoKI01hcDQgQXJyYW4gdnMuIFNjb3RsYW5kCkJlYXV0aWZ1bCBtYXAsIGJ1dCBJIGhhdmUgdG8gbGVhdmUgdGhlIGxhcHRvcCBydW5uaW5nIG92ZXJuaWdodCB0byBjb21waWxlIGl0LgpgYGB7ciBldmFsPUZBTFNFfQojSW1wb3J0IFVLIGRhdGEKRFpCb3VuZGFyaWVzMjAxNiA8LSByZWFkX3NmKCIuLi9hbGxkYXRhL1NHX1NJTURfMjAxNiIpClNjb3RsYW5kMjAxNiA8LSBhcyhEWkJvdW5kYXJpZXMyMDE2LCAiU3BhdGlhbCIpICU+JQpzcFRyYW5zZm9ybShDUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikpCgpEWkJvdW5kYXJpZXMyMDEyIDwtIHJlYWRfc2YoIi4uL2FsbGRhdGEvU0dfU0lNRF8yMDEyIikKU2NvdGxhbmQyMDEyIDwtIGFzKERaQm91bmRhcmllczIwMTIsICJTcGF0aWFsIikgJT4lCnNwVHJhbnNmb3JtKENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKCkRaQm91bmRhcmllczIwMDkgPC0gcmVhZF9zZigiLi4vYWxsZGF0YS9TR19TSU1EXzIwMDkiKQpTY290bGFuZDIwMDkgPC0gYXMoRFpCb3VuZGFyaWVzMjAwOSwgIlNwYXRpYWwiKSAlPiUKc3BUcmFuc2Zvcm0oQ1JTKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCIpKQoKRFpCb3VuZGFyaWVzMjAwNiA8LSByZWFkX3NmKCIuLi9hbGxkYXRhL1NHX1NJTURfMjAwNiIpClNjb3RsYW5kMjAwNiA8LSBhcyhEWkJvdW5kYXJpZXMyMDA2LCAiU3BhdGlhbCIpICU+JQpzcFRyYW5zZm9ybShDUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikpCgpEWkJvdW5kYXJpZXMyMDA0IDwtIHJlYWRfc2YoIi4uL2FsbGRhdGEvU0dfU0lNRF8yMDA0IikKU2NvdGxhbmQyMDA0IDwtIGFzKERaQm91bmRhcmllczIwMDQsICJTcGF0aWFsIikgJT4lCnNwVHJhbnNmb3JtKENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKCiNDb2xvdXIgUGFsYXRlCnBhbDIgPC0gY29sb3JOdW1lcmljKAogIHBhbGV0dGUgPSAidmlyaWRpcyIsCiAgZG9tYWluID0gMDoxMDApCgpsZWFmbGV0KCkgJT4lIAogIGFkZFRpbGVzKCkgJT4lIAogIHNldFZpZXcoLTUuMjI3NjgwLCA1NS41ODIzMzgsIHpvb20gPSAxMCkgJT4lIAoKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzMltleGFtcGxlc2hhcGVzMiR5ZWFyID09IDIwMDQsIF0sIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgbGFiZWwgPSBsaXN0bGlzdGxpc3RbMjk6MzVdLAogICAgICAgICAgICBncm91cCA9ICIyMDA0IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMDQiKSAlPiUgCiAgCmFkZFBvbHlnb25zKGRhdGE9U2NvdGxhbmQyMDA0LCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGdyb3VwID0gIlNjb3RsYW5kIDIwMDQiLAogICAgICAgICAgICBmaWxsT3BhY2l0eSA9MC44LAogICAgICAgICAgICBjb2xvciA9IH5wYWwyKFBlcmNlbnRpbGUpLAogICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJibGFjayIsIHdlaWdodCA9IDIsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpKSAlPiUgCmhpZGVHcm91cCgiU2NvdGxhbmQgMjAwNCIpICU+JSAKICAKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzMltleGFtcGxlc2hhcGVzMiR5ZWFyID09IDIwMDYsIF0sIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgbGFiZWwgPSBsaXN0bGlzdGxpc3RbMjI6MjhdLAogICAgICAgICAgICBncm91cCA9ICIyMDA2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMDYiKSAlPiUgCgphZGRQb2x5Z29ucyhkYXRhPVNjb3RsYW5kMjAwNiwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBncm91cCA9ICJTY290bGFuZCAyMDA2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIlNjb3RsYW5kIDIwMDYiKSAlPiUgCiAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlczJbZXhhbXBsZXNoYXBlczIkeWVhciA9PSAyMDA5LCBdLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gbGlzdGxpc3RsaXN0WzE1OjIxXSwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAwOSIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDA5IikgJT4lIAoKYWRkUG9seWdvbnMoZGF0YT1TY290bGFuZDIwMDksIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgZ3JvdXAgPSAiU2NvdGxhbmQgMjAwOSIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCJTY290bGFuZCAyMDA5IikgJT4lIAogIAphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMyW2V4YW1wbGVzaGFwZXMyJHllYXIgPT0gMjAxMiwgXSwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGxpc3RsaXN0bGlzdFs4OjE0XSwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAxMiIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDEyIikgJT4lIAogIAphZGRQb2x5Z29ucyhkYXRhPVNjb3RsYW5kMjAxMiwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBncm91cCA9ICJTY290bGFuZCAyMDEyIiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIlNjb3RsYW5kIDIwMTIiKSAlPiUgCgphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMyW2V4YW1wbGVzaGFwZXMyJHllYXIgPT0gMjAxNiwgXSwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGxpc3RsaXN0bGlzdFsxOjddLAogICAgICAgICAgICBncm91cCA9ICIyMDE2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMTYiKSAlPiUgCgphZGRQb2x5Z29ucyhkYXRhPVNjb3RsYW5kMjAxNiwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBncm91cCA9ICJTY290bGFuZCAyMDE2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIlNjb3RsYW5kIDIwMTYiKSAlPiUgCiAgCmFkZE1hcmtlcnMoCiAgICBsbmcgPSBjbGluaWNjb29yZGluYXRlcyRsb25naXR1ZGUsIGxhdCA9IGNsaW5pY2Nvb3JkaW5hdGVzJGxhdGl0dWRlLAogICAgbGFiZWwgPSBjbGluaWNjb29yZGluYXRlcyRYLAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IEYpLCBncm91cCA9IGNsaW5pY2Nvb3JkaW5hdGVzJFgpICU+JQogIGhpZGVHcm91cChjbGluaWNjb29yZGluYXRlcyRYKSAlPiUgICAKCmFkZExlZ2VuZCgiYm90dG9tbGVmdCIsIHBhbCA9IHBhbDIsIHZhbHVlcyA9IGV4YW1wbGVzaGFwZXMyJFBlcmNlbnRpbGUsCiAgICB0aXRsZSA9ICJTSU1EIFBlcmNlbnRpbGUiLAogICAgbGFiRm9ybWF0ID0gbGFiZWxGb3JtYXQoc3VmZml4ID0gIiUiKSwKICAgIG9wYWNpdHkgPSAxCiAgKSAgJT4lICAKCmFkZExheWVyc0NvbnRyb2woCiAgICBiYXNlR3JvdXBzID0gYygiMjAwNCIsICJTY290bGFuZCAyMDA0IiwgIjIwMDYiLCAiU2NvdGxhbmQgMjAwNiIsICIyMDA5IiwgIlNjb3RsYW5kIDIwMDkiLCAiMjAxMiIsICJTY290bGFuZCAyMDEyIiwgIjIwMTYiLCAiU2NvdGxhbmQgMjAxNiIsICJOb3RoaW5nIiksCiAgICBvdmVybGF5R3JvdXBzID0gYyhjbGluaWNjb29yZGluYXRlcyRYKSwKICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBUUlVFKQogICkKYGBgCgojTWFwNCBBcnJhbiB2cy4gU2NvdGxhbmQgTWFwCiFbTWFwNF0oZ2lmNC5naWYpCgojTWFwNQpJJ2xsIGNvbnRpbnVlIHRoaXMgb24gYSBuZXcgZG9jdW1lbnQgc28gSSBjYW4ga25pdCBpdCB0byBhbiBodG1sIHdlYnNpdGUuIAoKW01hcDUuXShNYXA1dmlldy5odG1sKQoKW01hcDUgQ29kZS5dKE1hcDVfQ29kZS5odG1sKQoKQnV0IHRoZSBkZXZlbG9wbWVudCBpcyB0aGF0IEkndmUgdXNlZCBpbnRlcnNlY3QoKSBvbiBlYWNoIGZpbHRlcmVkICdTR19TSU1EXy4uLicgdG8gY3JlYXRlIHRoZSAnc2hhcmVkdmFyaWFibGVzJyB2ZWN0b3IsIHNvIEkgd2FzIGFibGUgdG8gY3JlYXRlIGEgbmV3IGRhdGFmcmFtZSBvZiBldmVyeSB5ZWFyIHdpdGggb25seSBzaGFyZWQgdmFyaWFibGVzLCByYXRoZXIgdGhhbiBwZXJjZW50aWxlIGFsb25lICB3aGljaCBJIG9yaWdpbmFsbHkgdXNlZCBhcyBhbiBleGFtcGxlIHRvIHByYWN0aWNlIHRoZSBtYXBzIG9uIChteSBwcmV2aW91cyB2ZXJzaW9uIG9mICdhcnJhbnNpbWQnKS4KVGhlIG5ldyAnYXJyYW5TSU1EJyBjYW4gdGhlbiBoYXZlIGEgdmVyc2lvbiBvZiBtYXAzIGZvciBlYWNoIHNoYXJlZCB2YXJpYWJsZS4KCltHbyBiYWNrLl0oaHR0cHM6Ly9mZXJndXN0YXlsb3IuZ2l0aHViLmlvL0FycmFuKQoK